#include "Precompile.h"
#include "GraphicsFactory.h"
#include "CEGUIManager.h"

#ifdef TARGET_DX11
	#include "DX11RenderSystem.h"
	#include "DX11VertexBuffer.h"
	#include "DX11IndexBuffer.h"
	#include "DX11RenderTarget.h"
	#include "DX11PixelShader.h"
	#include "DX11VertexShader.h"
	#include "DX11ComputeShader.h"
	#include "DX11Texture2D.h"
	#include "DX11TextureCube.h"
#elif defined TARGET_DX10
	#include "DX10RenderSystem.h"
	#include "DX10VertexBuffer.h"
	#include "DX10IndexBuffer.h"
	#include "DX10RenderTarget.h"
	#include "DX10PixelShader.h"
	#include "DX10VertexShader.h"
	#include "DX10ComputeShader.h"
	#include "DX10Texture2D.h"
	#include "DX10TextureCube.h"
#elif defined TARGET_DX9
	#include "DX9RenderSystem.h"
	#include "DX9VertexBuffer.h"
	#include "DX9IndexBuffer.h"
	#include "DX9RenderTarget.h"
	#include "DX9PixelShader.h"
	#include "DX9VertexShader.h"
	#include "DX9ComputeShader.h"
	#include "DX9Texture2D.h"
	#include "DX9TextureCube.h"
#endif

namespace Graphics{
	RenderContext* GraphicsFactory::m_renderContext = NULL;

	RenderSystemPtr GraphicsFactory::createRenderSystem(RenderMode &mode, RenderSystemPlatform platform){
#ifdef TARGET_DX11
		return RenderSystemPtr( new DX11RenderSystem(mode) );
#elif defined TARGET_DX10
		return RenderSystemPtr( new DX10RenderSystem(mode) );
#elif defined TARGET_DX9
		return RenderSystemPtr( new DX9RenderSystem(mode) );
#endif
		return RenderSystemPtr();
	}

	GUIManagerPtr GraphicsFactory::createGUIManager(){
		return GUIManagerPtr(new CEGUIManager);
		return GUIManagerPtr();
	}

	boost::shared_ptr<RenderTarget> GraphicsFactory::createRenderTarget(Texture2DPtr texture){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createRenderTarget - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return boost::shared_ptr<RenderTarget>( new DX11RenderTarget(texture,m_renderContext) );
#elif defined TARGET_DX10
		return boost::shared_ptr<RenderTarget>( new DX10RenderTarget(texture,m_renderContext) );
#elif defined TARGET_DX9
		return boost::shared_ptr<RenderTarget>( new DX9RenderTarget(texture,m_renderContext) );
#endif
		return boost::shared_ptr<RenderTarget>( );
	}

	boost::shared_ptr<VertexBuffer> GraphicsFactory::createVertexBuffer(VertexDataPtr verts){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createVertexBuffer - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return boost::shared_ptr<VertexBuffer>( new DX11VertexBuffer(verts,m_renderContext) );
#elif defined TARGET_DX10
		return boost::shared_ptr<VertexBuffer>( new DX10VertexBuffer(verts,m_renderContext) );
#elif defined TARGET_DX9
		return boost::shared_ptr<VertexBuffer>( new DX9VertexBuffer(verts,m_renderContext) );
#endif
		return boost::shared_ptr<VertexBuffer>( );
	}

	boost::shared_ptr<IndexBuffer> GraphicsFactory::createIndexBuffer(IndexDataPtr inds){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createIndexBuffer - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return boost::shared_ptr<IndexBuffer>( new DX11IndexBuffer(inds,m_renderContext) );
#elif defined TARGET_DX10
		return boost::shared_ptr<IndexBuffer>( new DX10IndexBuffer(inds,m_renderContext) );
#elif defined TARGET_DX9
		return boost::shared_ptr<IndexBuffer>( new DX9IndexBuffer(inds,m_renderContext) );
#endif
		return boost::shared_ptr<IndexBuffer>( );
	}

	PixelShaderPtr GraphicsFactory::createPixelShader(std::string &filename){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createPixelShader - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return PixelShaderPtr( new DX11PixelShader(filename,m_renderContext) );
#elif defined TARGET_DX10
		return PixelShaderPtr( new DX10PixelShader(filename,m_renderContext) );
#elif defined TARGET_DX9
		return PixelShaderPtr( new DX9PixelShader(filename,m_renderContext) );
#endif
		return PixelShaderPtr();
	}

	VertexShaderPtr GraphicsFactory::createVertexShader(std::string &filename){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createVertexShader - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return VertexShaderPtr( new DX11VertexShader(filename,m_renderContext) );
#elif defined TARGET_DX10
		return VertexShaderPtr( new DX10VertexShader(filename,m_renderContext) );
#elif defined TARGET_DX9
		return VertexShaderPtr( new DX9VertexShader(filename,m_renderContext) );
#endif
		return VertexShaderPtr();
	}

	ComputeShaderPtr GraphicsFactory::createComputeShader(std::string &filename){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createComputeShader - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return ComputeShaderPtr( new DX11ComputeShader(filename,m_renderContext) );
#elif defined TARGET_DX10
		return ComputeShaderPtr( new DX10ComputeShader(filename,m_renderContext) );
#elif defined TARGET_DX9
		return ComputeShaderPtr( new DX9ComputeShader(filename,m_renderContext) );
#endif
		return ComputeShaderPtr();
	}

	Texture2DPtr GraphicsFactory::createTexture2D(std::string &filename,Texture2D::ShaderResourceSlot slot){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createComputeShader - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return Texture2DPtr( new DX11Texture2D(filename,slot,m_renderContext) );
#elif defined TARGET_DX10
		return Texture2DPtr( new DX10Texture2D(filename,slot,m_renderContext) );
#elif defined TARGET_DX9
		return Texture2DPtr( new DX9Texture2D(filename,slot,m_renderContext) );
#endif
		return Texture2DPtr();
	}

	Texture2DPtr GraphicsFactory::createEmptyTexture2D(int width, int height, int multisample, Texture2D::ShaderResourceSlot slot, TextureFormat format){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createComputeShader - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return Texture2DPtr( new DX11Texture2D(width,height,multisample,slot,format,m_renderContext) );
#elif defined TARGET_DX10
		return Texture2DPtr( new DX10Texture2D(width,height,slot,format,m_renderContext) );
#elif defined TARGET_DX9
		return Texture2DPtr( new DX9Texture2D(width,height,slot,format,m_renderContext) );
#endif
		return Texture2DPtr();
	}

	TextureCubePtr GraphicsFactory::createTextureCube(std::string& top, std::string& bottom, std::string& left, std::string& right, std::string& front, std::string& back){
		if(!m_renderContext){
			LOG_ERROR("GraphicsFactory::createTextureCube - Context not available.");
			assert(0);
		}

#ifdef TARGET_DX11
		return TextureCubePtr( new DX11TextureCube(top,bottom,left,right,front,back,m_renderContext) );
#elif defined TARGET_DX10
		return TextureCubePtr( new DX10TextureCube(filename,slot,m_renderContext) );
#elif defined TARGET_DX9
		return TextureCubePtr( new DX9TextureCube(filename,slot,m_renderContext) );
#endif
		return TextureCubePtr();
	}
};